package com.bytedy.sboot.config;

import com.bytedy.sboot.support.auth.UserLoginAuthenticationFilter;
import com.bytedy.sboot.support.auth.UserLoginConfigurer;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletRequest;
import jakarta.servlet.ServletResponse;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.ProviderManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configurers.*;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.FilterChainProxy;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.access.intercept.AuthorizationFilter;

/**
 * Date: 2024/5/28 16:01
 * Author: ByteDy
 */
@SuppressWarnings("all")
// @ConditionalOnDefaultWebSecurity
@Configuration
public class SecurityConfiguration {


    @Resource
    UserDetailsService userService;

    /**
     * ${@link AuthorizationFilter, FilterChainProxy}
     * {@link FilterChainProxy.VirtualFilterChain#doFilter(ServletRequest, ServletResponse)}
     *
     * @param http
     * @return
     * @throws Exception
     */
    @Bean
    SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {

        // http.formLogin(Customizer.withDefaults());
        // http.httpBasic(Customizer.withDefaults());
        http.removeConfigurers(AnonymousConfigurer.class);
        http.removeConfigurers(LogoutConfigurer.class);
        http.removeConfigurers(DefaultLoginPageConfigurer.class);
        // http.removeConfigurers(AuthorizeHttpRequestsConfigurer.class);
        http.removeConfigurers(CsrfConfigurer.class);
        http.removeConfigurers(CorsConfigurer.class);
        http.removeConfigurers(ServletApiConfigurer.class);
        http.removeConfigurers(RequestCacheConfigurer.class);
        http.removeConfigurers(HeadersConfigurer.class);
        http.sessionManagement(sessionConfig -> {
            // sessionConfig.invalidSessionUrl("/login");
            // 转发的时候会再过一遍 SecurityFilterChain，例如对错误路径 /error
            sessionConfig.enableSessionUrlRewriting(false);
            // sessionConfig.sessionAuthenticationStrategy()
        });

        http.authorizeHttpRequests(requests -> {
            requests.requestMatchers("/login").permitAll();
            requests.anyRequest().authenticated();
        });


        // http.removeConfigurers(ExceptionHandlingConfigurer.class);
        // org.apache.catalina.valves.ErrorReportValve.report
        // 这里需要打开，否则异常会回到tomcat里进行处理，tomcat默认逻辑包含错误网页返回 ErrorReportValve.report ，不需要
        http.exceptionHandling(s -> {
            s.accessDeniedHandler(new UserLoginAuthenticationFilter.FailureHandler());
            s.authenticationEntryPoint(new UserLoginAuthenticationFilter.FailureHandler());
        });


        // UserLoginAuthenticationFilter authenticationFilter = new UserLoginAuthenticationFilter();
        // // authenticationFilter.setFilterProcessesUrl("/login");
        // authenticationFilter.setAuthenticationSuccessHandler(new UserLoginAuthenticationFilter.SuccessHandler());
        // authenticationFilter.setAuthenticationFailureHandler(new UserLoginAuthenticationFilter.FailureHandler());
        // authenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login"));
        // authenticationFilter.setAuthenticationManager(authenticationManager());
        // authenticationFilter.setAllowSessionCreation(true);
        // http.getConfigurer(SessionManagementConfigurer.class).init(http);
        // authenticationFilter.setSessionAuthenticationStrategy(http.getSharedObject(SessionAuthenticationStrategy.class));
        // http.addFilter(authenticationFilter);


        // 注意：UserLoginAuthenticationFilter注掉改用Configurer注册，否则有很多的属性类会丢失
        UserLoginConfigurer<HttpSecurity> userLoginConfigurer = new UserLoginConfigurer<>();
        userLoginConfigurer.successHandler(new UserLoginAuthenticationFilter.SuccessHandler());
        userLoginConfigurer.failureHandler(new UserLoginAuthenticationFilter.FailureHandler());
        http.apply(userLoginConfigurer);
        // userLoginConfigurer.configure(http);

        http.authenticationManager(authenticationManager());

        return http.build();
    }

    // @Bean
    // public WebSecurityCustomizer webSecurityCustomizer() {
    //
    //     return (web) -> web.ignoring().antMatchers("/ignore1", "/ignore2");
    // }


    @Bean
    public AuthenticationManager authenticationManager() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userService);
        return new ProviderManager(daoAuthenticationProvider);
    }


}
